import { Authority, AuthorityService } from "@mallfoundry/keystone/security"
import { Tree } from "antd"
import * as _ from "lodash"
import * as React from "react"
import { useEffect, useState } from "react"

type UseAuthorityType = [AuthorityNode, string[]]

class AuthorityNode {
  public key: string = ""
  public authority: string = ""
  public name: string = ""
  public title: string = ""
  public children?: AuthorityNode[]
}

function authorityNode(authority: Authority, allKeys: string[], authorities: string[] = [], readonly: boolean = false): undefined | AuthorityNode {
  const node = _.assign(new AuthorityNode(), authority, {
    key: authority.code,
    title: authority.name,
    children: _.chain(authority.children)
      .filter(aChild => !readonly || authorities.includes(aChild.code as string) || !_.isEmpty(aChild.children))
      .map(aChild => authorityNode(aChild, allKeys, authorities, readonly))
      .compact()
      .value(),
  })
  if (readonly && _.isEmpty(node.children) && !_.includes(authorities, node.authority)) {
    return undefined
  }
  allKeys.push(node.key)
  return node
}

function useAuthorityDescription(authorities: string[] = [], readonly: boolean = false): UseAuthorityType {
  const [node, setNode] = useState(new AuthorityNode())
  const [allKeys, setAllKeys] = useState([] as string[])

  useEffect(() => {
    const newAllKeys = [] as string[]
    AuthorityService
      .getAuthority({ code: "store_manage" })
      .then(description => authorityNode(description, newAllKeys, authorities, readonly))
      .then(node => {
        if (node) {
          setNode(node)
        }
      })
      .then(() => setAllKeys(newAllKeys))
  }, [authorities, readonly])

  return [node, allKeys]
}


interface RoleAuthoritiesProps {
  readonly?: boolean
  authorities?: string[]
  onChange?: (authorities: string[]) => void
}

export default function RoleAuthorities(props: RoleAuthoritiesProps) {
  const { authorities, readonly, onChange } = props
  const [descriptionNode, allDescriptionNodeKeys] = useAuthorityDescription(authorities, readonly)

  return (<Tree checkable={!readonly}
                selectable={false}
                treeData={[descriptionNode]}
                expandedKeys={allDescriptionNodeKeys}
                checkedKeys={authorities}
                onCheck={checkedKeys => {
                  if (_.isFunction(onChange)) {
                    // @ts-ignore
                    onChange(checkedKeys)
                  }
                }}/>)
}
